module  ctr
        (inst,regdst,ext,aluop,regwr,memrd,memwr,memtoreg,alusrc2,branch,j,jr,createdump,lbi,rti,siic);
//module ctr(inst,regdst,jump,branch,memrd,memreg,aluop,memwt,alusrc,regwr);
    input   [4:0]   inst;
    output  [1:0]   regdst;
    output  [2:0]   ext;
    output  [3:0]   aluop;
    output          regwr;
    output          memrd;
    output          memwr;
    output          memtoreg;
    output          alusrc2;
    output  [2:0]   branch;
    output          j;
    output          jr;
    output          createdump;
    output          lbi;
    output          rti,siic;

    wire    a=inst[4];
    wire    b=inst[3];
    wire    c=inst[2];
    wire    d=inst[1];
    wire    e=inst[0];

    //  regdst  determine write address in register file
    //          00  inst[4:2]   all the R-format
    //          01  inst[10:8]  lbi,slbi,stu
    //          10  inst[7:5]   all the I1-format (except for stu)
    //          11  jal,jalr
    assign  regdst =    (inst[4:2] == 5'b010)?2'b10
                    :   (inst[4:2] == 5'b101)?2'b10
                    :   (inst[4:1] == 4'b1000)?2'b10
                    :   (inst == 5'b10011)?2'b01
                    :   (inst == 5'b11000)?2'b01
                    :   (inst == 5'b10010)?2'b01
                    :   (inst[4:1] == 4'b0011)?2'b11:2'b00;

    assign  ext =   ({{inst[4:2]},inst[0]}==4'b0010)?3'b100
                :   ({{inst[4:2]},inst[0]}==4'b0011)?3'b011
                :   (inst[4:2]==3'b011)?3'b011
                :   (inst==5'b11000)?3'b011
                :   (inst==5'b10010)?3'b010
                :   (inst[4:1]==4'b0101)?3'b000 : 3'b001;

    assign  aluop = (inst[4:2]==3'b010)? {2'b00,inst[1:0]}
                :   (inst[4:2]==3'b101)? {2'b01,inst[1:0]}
                :   (inst[4:2]==3'b111)? {2'b11,inst[1:0]}
                :   (inst[4:1]==4'b1000)? 4'b0000
                :   ({{inst[4:2]},inst[0]}==4'b0010)?4'b0000
                :   (inst[4:1]==4'b0011)? 4'b0000
                :   (inst==5'b10011)? 4'b0000
                :   (inst==5'b00101)? 4'b0000
                :   (inst==5'b10010)? 4'b1001
                :   (inst==5'b11001)? 4'b1000 :{2'b10,inst[1:0]};
    //  regwr   register file write control
    //      1:  010xx,101xx,100x1,110x1,1101x,111xx,11000,10010,00110,00111
    //      1:  010xx,1xxx1,1x1xx,110x0,10010,0011x
    assign  regwr = ~a&b&~c | a&e | a&c | a&b&~c&~e | a&~b&~c&d&~e | ~a&~b&c&d;
    //  memrd/wr memory read/write control
    //  10000           memwr
    //  10001   memrd
    //  10011           memwr
    assign  memrd = a&~b&~c&~d&e;
    assign  memwr = a&~b&~c&(~d^e);
    //  memtoreg    select signals to write back to register file(0:alu,1:memory)
    //  memtoreg makes sense only when regwr is asserted
    //  0:  010xx,101xx,10011,110x1,1101x,111xx,11000,10010,00110,00111
    //  1:  10001
    assign  memtoreg = (inst==5'b10001)?1'b1:~regwr;
    //  aluop2: select signals as 2nd operands of alu (0:Rt,1:immd)
    //  Immd:   010xx,101xx,1000x,100x1,10010,001x1
    //  Rt:     1101x,111xx,
    assign  alusrc2 = ~a&b&~c | a&~b&c | a&~b&~c&~d | a&~b&~c&e | a&~b&~c&d&~e | ~a&~b&c&e;
    //  branch: beqz,bnez,bltz,bgez
    assign  branch = (inst[4:2]==3'b011)?{1'b1,inst[1:0]}:3'b000;
    //  j:      j,jal
    assign  j = ~a&~b&c&~e;
    //  jr:     jr,jalr
    assign  jr = ~a&~b&c&e;
    //  jal:    jal,jalr
    assign  createdump = (inst==5'b00000)?1'b1:1'b0;
    assign  lbi = a&b&~c&~d&~e;
    assign  siic = ~a&~b&~c&d&~e;
    assign  rti = ~a&~b&~c&d&e;

endmodule
